package cn.universal.plugins.protocolapi.servlet;

import cn.universal.plugins.protocolapi.core.config.MagicAPIProperties;
import cn.universal.plugins.protocolapi.core.interceptor.AuthorizationInterceptor;
import cn.universal.plugins.protocolapi.core.servlet.MagicRequestContextHolder;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MagicJakartaServletConfiguration implements WebMvcConfigurer {

  private final MagicAPIProperties properties;

  private final MagicJakartaCorsFilter magicCorsFilter = new MagicJakartaCorsFilter();

  private final ObjectProvider<MagicJakartaWebRequestInterceptor>
      magicWebRequestInterceptorProvider;

  public MagicJakartaServletConfiguration(
      MagicAPIProperties properties,
      ObjectProvider<MagicJakartaWebRequestInterceptor> magicWebRequestInterceptorProvider) {
    this.properties = properties;
    this.magicWebRequestInterceptorProvider = magicWebRequestInterceptorProvider;
  }

  @Bean
  public MagicRequestContextHolder magicRequestContextHolder(MultipartResolver multipartResolver) {
    return new MagicJakartaRequestContextHolder(multipartResolver);
  }

  @Bean
  public MagicJakartaWebRequestInterceptor magicWebRequestInterceptor(
      AuthorizationInterceptor authorizationInterceptor) {
    return new MagicJakartaWebRequestInterceptor(
        properties.isSupportCrossDomain() ? magicCorsFilter : null, authorizationInterceptor);
  }

  @Bean
  public MagicJakartaResponseExtension magicJakartaResponseExtension() {
    return new MagicJakartaResponseExtension();
  }

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    resolvers.add(0, new MagicJakartaHttpServletRequest.ArgumentsResolver());
    resolvers.add(0, new MagicJakartaHttpServletResponse.ArgumentsResolver());
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(magicWebRequestInterceptorProvider.getObject()).addPathPatterns("/**");
  }

  @Bean
  @ConditionalOnProperty(
      prefix = "magic-api",
      value = "support-cross-domain",
      havingValue = "true",
      matchIfMissing = true)
  public FilterRegistrationBean<MagicJakartaCorsFilter> magicCorsFilterRegistrationBean() {
    FilterRegistrationBean<MagicJakartaCorsFilter> registration =
        new FilterRegistrationBean<>(magicCorsFilter);
    registration.addUrlPatterns("/magic/**");
    registration.setName("Magic Cors Filter");
    registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return registration;
  }
}
